package com.mfs.common.utills;

import java.util.UUID;

/**
 *
 * @author mfs
 * @date 2022/08/14
 * */
public class IdUtil {
    /**
     * UUID
     * */
    public static String randomUUID() {
        return UUID.randomUUID().toString();
    }


    /**
     * 雪花算法生成id
     * */
    public static SnowId snowId() {
        return new SnowId();
    }

    public static SnowId snowId(long centerId, long serviceId) {
        return new SnowId(centerId, serviceId);
    }

    public static SnowId snowId(long begin, long centerId, long serviceId) {
        return new SnowId(begin, centerId, serviceId);
    }

    public static class SnowId {
        /**
         * 最大序列号
         * */
        private static final long MAX_SEQUENCE = 4096 - 1;
        /**
         * 基准时间
         * */
        private long begin = 0;
        /**
         * 机房编号
         * */
        private long centerId = 1 << 17;
        /**
         * 服务编号
         * */
        private long serviceId = 1 << 12;

        /**
         * 上次生成编号的时间
         * */
        private volatile long lastTime = System.currentTimeMillis();
        /**
         * 上次生成的序列号
         * */
        private volatile long sequence = 0;

        private SnowId() {
        }

        private SnowId(long centerId, long serviceId) {
            this.centerId = centerId;
            this.serviceId = serviceId;
        }

        private SnowId(long begin, long centerId, long serviceId) {
            this.begin = begin;
            this.centerId = centerId;
            this.serviceId = serviceId;
        }

        /**
         * 雪花算法产生id
         * */
        public synchronized long snowId() {
            long currentTime = System.currentTimeMillis();
            while (currentTime < lastTime) {
                currentTime = System.currentTimeMillis();
            }
            if (currentTime == lastTime) {
                if (sequence >= MAX_SEQUENCE) {
                    while (currentTime == lastTime) {
                        currentTime = System.currentTimeMillis();
                    }
                    sequence = 0;
                } else {
                    sequence ++;
                }
            } else {
                sequence = 0;
            }
            lastTime = currentTime;
            long res = ((currentTime - begin) << 22 ^ centerId ^ serviceId ^ sequence);
            if (res < 0) {
                throw new RuntimeException("雪花算法生成id失败");
            }
            return res;
        }
    }
}
